﻿using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace CAD.Service
{
    public static class DocumentExtension
    {

        /// <summary>
        /// 获取数据库对应的文档对象
        /// </summary>
        /// <param name="db">数据库对象</param>
        /// <returns>返回数据库对应的文档对象</returns>
        public static Document GetDocument(this Database db)
        {
            return Application.DocumentManager.GetDocument(db);
        }

        /// <summary>
        /// 根据数据库获取命令行对象
        /// </summary>
        /// <param name="db">数据库对象</param>
        /// <returns>返回命令行对象</returns>
        public static Editor GetEditor(this Database db)
        {
            return Application.DocumentManager.GetDocument(db).Editor;
        }

        public static T OpenInMode<T>(this Entity entity, OpenMode openMode, bool openErased = true, bool forceOpenOnLockedLayer = true) where T : class
        {
            return entity.ObjectId.OpenInMode<T>(openMode, openErased, forceOpenOnLockedLayer) as T;
        }

        public static T OpenInMode<T>(this ObjectId objectId, OpenMode openMode, bool openErased = true, bool forceOpenOnLockedLayer = true) where T : class
        {
            return objectId.GetObject(openMode, openErased, forceOpenOnLockedLayer) as T;
        }



        public static ObjectId AddToModelSpace(this Database database, Entity ent, bool needLock = true)
        {
            ObjectId entId = ObjectId.Null;//用于返回添加到模型空间中的实体ObjectId

            Action action = new Action(() =>
            {
                using (Transaction trans = database.TransactionManager.StartTransaction())
                {
                    //以读方式打开块表
                    BlockTable bt = (BlockTable)trans.GetObject(database.BlockTableId, OpenMode.ForRead);
                    var spaceId = bt[BlockTableRecord.ModelSpace];

                    //以写方式打开模型空间块表记录.
                    if (trans.GetObject(spaceId, OpenMode.ForWrite) is BlockTableRecord btr)
                    {
                        entId = btr.AppendEntity(ent);//将图形对象的信息添加到块表记录中
                        trans.AddNewlyCreatedDBObject(ent, true);//把对象添加到事务处理中
                    }
                    trans.Commit();//提交事务处理
                }
            });

            if (needLock)
            {
                Document document = database.GetDocument();
                using (DocumentLock docLock = document.LockDocument())
                {
                    //add to modelspace 加入模型空间
                    action.Invoke();
                }
            }
            else
            {
                action.Invoke();
            }

            return entId; //返回实体的ObjectId
        }



        public static ObjectId AttachEntity(this Database database, Entity ent, bool needLock = true)
        {
            ObjectId entId = ObjectId.Null;//用于返回添加到模型空间中的实体ObjectId

            Action action = new Action(() =>
            {
                using (Transaction trans = database.TransactionManager.StartTransaction())
                {
                    //以读方式打开块表
                    BlockTable bt = (BlockTable)trans.GetObject(database.BlockTableId, OpenMode.ForRead);
                    var spaceId = bt[BlockTableRecord.ModelSpace];

                    //以写方式打开模型空间块表记录.
                    BlockTableRecord btr = (BlockTableRecord)trans.GetObject(spaceId, OpenMode.ForWrite);
                    entId = btr.AppendEntity(ent);//将图形对象的信息添加到块表记录中
                    trans.AddNewlyCreatedDBObject(ent, true);//把对象添加到事务处理中

                    trans.Commit();//提交事务处理
                }

                //using (Transaction trans = database.TransactionManager.StartTransaction())
                //{
                //    //以读方式打开块表
                //    BlockTable bt = database.BlockTableId.GetObject(OpenMode.ForRead, true, true) as BlockTable;
                //    var spaceId = bt[BlockTableRecord.ModelSpace];

                //    //以写方式打开模型空间块表记录.
                //    BlockTableRecord btr = spaceId.GetObject(OpenMode.ForWrite, true, true) as BlockTableRecord;
                //    entId = btr.AppendEntity(ent);//将图形对象的信息添加到块表记录中
                //    trans.AddNewlyCreatedDBObject(ent, true);//把对象添加到事务处理中

                //    trans.Commit();//提交事务处理
                //}
            });

            if (needLock)
            {
                //Document document = database.GetDocument();
                //using (DocumentLock docLock = document.LockDocument())
                //{
                //    //add to modelspace 加入模型空间
                //    action.Invoke();
                //}

                //构造锁运行
                action = action.BuildDocumentLock(database);
            }
            else
            {
                action.Invoke();
            }

            return entId; //返回实体的ObjectId

        }

        public static ObjectId AttachEntity(this Database database, IEnumerable<Entity> entitys, bool needLock = true)
        {
            ObjectId entId = ObjectId.Null;//用于返回添加到模型空间中的实体ObjectId

            Action action = new Action(() =>
            {
                using (Transaction trans = database.TransactionManager.StartTransaction())
                {
                    //以读方式打开块表
                    BlockTable bt = (BlockTable)trans.GetObject(database.BlockTableId, OpenMode.ForRead);
                    var spaceId = bt[BlockTableRecord.ModelSpace];

                    //以写方式打开模型空间块表记录.
                    BlockTableRecord btr = (BlockTableRecord)trans.GetObject(spaceId, OpenMode.ForWrite);
                    foreach (Entity ent in entitys)
                    {
                        entId = btr.AppendEntity(ent);//将图形对象的信息添加到块表记录中
                        trans.AddNewlyCreatedDBObject(ent, true);//把对象添加到事务处理中
                    }

                    trans.Commit();//提交事务处理
                }

                //using (Transaction trans = database.TransactionManager.StartTransaction())
                //{
                //    //以读方式打开块表
                //    BlockTable bt = database.BlockTableId.GetObject(OpenMode.ForRead, true, true) as BlockTable;
                //    var spaceId = bt[BlockTableRecord.ModelSpace];

                //    //以写方式打开模型空间块表记录.
                //    BlockTableRecord btr = spaceId.GetObject(OpenMode.ForWrite, true, true) as BlockTableRecord;
                //    entId = btr.AppendEntity(ent);//将图形对象的信息添加到块表记录中
                //    trans.AddNewlyCreatedDBObject(ent, true);//把对象添加到事务处理中

                //    trans.Commit();//提交事务处理
                //}
            });

            if (needLock)
            {
                //Document document = database.GetDocument();
                //using (DocumentLock docLock = document.LockDocument())
                //{
                //    //add to modelspace 加入模型空间
                //    action.Invoke();
                //}

                //构造锁运行
                action = action.BuildDocumentLock(database);
            }
            else
            {
                action.Invoke();
            }

            return entId; //返回实体的ObjectId

        }
         

        /// <summary>
        /// 构造transaction的运行方法
        /// </summary>
        /// <param name="action"></param>
        /// <param name="database"></param>
        /// <returns></returns>
        public static Action BuildTransaction(this Action action, Database database)
        {
            Action transAction = new Action(() =>
            {
                using (Transaction transaction = database.TransactionManager.StartTransaction())
                {
                    try
                    {
                        action.Invoke();
                    }
                    catch (System.Exception exp)
                    {
                        database.GetEditor().WriteMessage($"\n transaction error :{exp.ToString()}\n ");
                        transaction.Abort();
                    }
                    transaction.Commit();
                }
            });
            return transAction;
        }

        /// <summary>
        /// 构造锁 用于非模态界面的按钮执行  纯命令运行不需要该方法
        /// </summary>
        /// <param name="action"></param>
        /// <param name="database"></param>
        /// <returns></returns>
        public static Action BuildDocumentLock(this Action action, Database database)
        {
            Document document = database.GetDocument();
            using (DocumentLock docLock = document.LockDocument())
            {
                try
                {
                    action.Invoke();
                }
                catch (System.Exception exp)
                {
                    database.GetEditor().WriteMessage($"\ndocLock error :{exp.ToString()}\n ");
                }
            }
            return action;
        }

        //public static Action BuildDocumentLock(this Action action, Document document)
        //{
        //    using (DocumentLock docLock = document.LockDocument())
        //    { 
        //        action.Invoke();
        //    }
        //    return action;
        //}


    }
}
